
#include "fifoBuf.h"
#include "Sys.h"
//#include "utils.h"
#include "macros.h"
#include "debug.h"

/* void Fifo_Init(FIFO_INF* fi, unsigned char* FifoBuffer, unsigned int BufferSize); */

/* /\* return - bytes number puted into fifo or (-1) if no place to write *\/ */
/* int Fifo_Write(FIFO_INF* fi, unsigned char* DataBuffer, unsigned int ByteCount); */

/* /\* Read from FifoBuffer to DataBuffer; return - numbers of bytes was puted to DataBuffer *\/ */
/* int Fifo_Read(FIFO_INF* fi, unsigned char* DataBuffer); */

/* /\* return - how many bytes available to write *\/ */
/* int Fifo_AvailableToWrite(FIFO_INF* fi); */


void Fifo_Init(FIFO_INF* fi, unsigned char* FifoBuffer, int BufferSize)
{
	fi->pWrite = 0;
	fi->pRead = 0;
	fi->BufferSize = BufferSize;
	fi->FifoBuffer = FifoBuffer;
	fi->AvailabelEntryCount = 0;
}

int Fifo_AvailableToRead(FIFO_INF* fi)
{
	return ((fi->BufferSize + fi->pWrite - fi->pRead) % fi->BufferSize);
}

int Fifo_AvailableToWrite(FIFO_INF* fi)
{
	return (fi->BufferSize - 1 - Fifo_AvailableToRead(fi));
}


int Fifo_i_Write(FIFO_INF* fi, unsigned char* DataBuffer, unsigned int ByteCount)
{
	int i = 0;
	
	if ( Fifo_AvailableToWrite(fi) >= ByteCount )
	{  
		for ( i = 0; i < ByteCount; i++ )
		{
			fi->FifoBuffer[fi->pWrite++] = *DataBuffer++;
		
			if ( fi->pWrite >= fi->BufferSize )
			{
				fi->pWrite = 0;
			}
		} 
	}
	else
	{
		i = (-1);
	}
	
	return i;
}

int Fifo_Write(FIFO_INF* fi, unsigned char* DataBuffer, unsigned int ByteCount)
{
	int i = 0;
	
	int save_status_reg = 0;
	save_status_reg = cpu_save_sr();

	if ( Fifo_AvailableToWrite(fi) >= ByteCount )
	{  
		for ( i = 0; i < ByteCount; i++ )
		{
			fi->FifoBuffer[fi->pWrite++] = *DataBuffer++;
		
			if ( fi->pWrite >= fi->BufferSize )
			{
				fi->pWrite = 0;
			}
		} 
	}
	else
	{
		i = (-1);
	}

	cpu_restore_sr(save_status_reg);
	
	return i;
}


//#define   FIFO_ENTRY_WRITE_BYTE(FIFO_ENTRY fe, unsigned char Ch)	fe->pWrite++;


int Fifo_Read(FIFO_INF* fi, unsigned char* DataBuffer)
{
	int i = 0;
	
	int save_status_reg = 0;
	save_status_reg = cpu_save_sr();

	for(;;)
	{
		if ( fi->pRead == fi->pWrite )
		{
			break;
		}
		
		DataBuffer[i++] = fi->FifoBuffer[fi->pRead++];
		
		if ( fi->pRead >= fi->BufferSize )
		{
			fi->pRead = 0;
		}
	}
	
	cpu_restore_sr(save_status_reg);

	return i;
}


int Fifo_nRead(FIFO_INF* fi, unsigned char* DataBuffer, unsigned int ByteToRead)
{
	int i = 0;
	
	int save_status_reg = 0;
	save_status_reg = cpu_save_sr();

	for(;;)
	{
		if ( fi->pRead == fi->pWrite )
		{
			break;
		}
		
		DataBuffer[i++] = fi->FifoBuffer[fi->pRead++];
				
		if ( fi->pRead >= fi->BufferSize )
		{
			fi->pRead = 0;
		}

		if ( i >= ByteToRead )
		{
			break;
		}
	}
	
	cpu_restore_sr(save_status_reg);

	return i;
}

/* FIFO ENTRY */

/* in interrupt using for;  */
int Fifo_Entry_i_Puts(FIFO_INF* fi, unsigned char* DataBuffer, unsigned int ByteCount)
{
	int i; // , ByteCount;
	
/* 	ByteCount = StrLen((const char*)DataBuffer); */
/* 	ByteCount++;					  /\* place for zero *\/ */

	if ( Fifo_AvailableToWrite(fi) >= ByteCount )
	{  
		for ( i = 0; i < ByteCount; i++ )
		{
			fi->FifoBuffer[fi->pWrite++] = *DataBuffer++;
		
			if ( fi->pWrite >= fi->BufferSize )
			{
				fi->pWrite = 0;
			}
		}
		fi->AvailabelEntryCount++;
	}
	else
	{
		i = (-1);
	}

	return i;
}

int Fifo_Entry_i_PutCh(FIFO_INF* fi, unsigned char Ch)
{
	int i;
	
	if ( Fifo_AvailableToWrite(fi) >= 1 )
	{  
		fi->FifoBuffer[fi->pWrite++] = Ch;
		
		if ( fi->pWrite >= fi->BufferSize )
		{
			fi->pWrite = 0;
		}
	}
	else
	{
		i = (-1);
	}

	return i;
}

int Fifo_Entry_Read(FIFO_INF* fi, unsigned char* DataBuffer)
{
	int i = 0;
	
	int save_status_reg = 0;
	save_status_reg = cpu_save_sr();

	if ( fi->AvailabelEntryCount > 0 )
	{
		for(;;)
		{
/* 			if ( fi->pRead == fi->pWrite ) */
/* 			{ */
/* 				DBG_OUT("\r ERROR: Fifo_Entry_Read\r"); */
/* 				break; */
/* 			} */
		
			DataBuffer[i++] = fi->FifoBuffer[fi->pRead++];
					
			if ( fi->pRead >= fi->BufferSize )
			{
				fi->pRead = 0;
			}

			if ( DataBuffer[i-1] == 0 ) /* end of entry (string) */
			{
				fi->AvailabelEntryCount--;
				break;
			}
		}
	}
	
	cpu_restore_sr(save_status_reg);

	return i;
}

/* return - pointer at the available Entry if MessageStatus = 1, do the Entry as read */
unsigned char* Fifo_Entry_Get(FIFO_INF* fi, int MessageStatus)
{
	int tmp;
	unsigned char* p;

	p = NULL;

	int save_status_reg = 0;
	save_status_reg = cpu_save_sr();

  
	if ( fi->AvailabelEntryCount > 0 )
	{
		if ( MessageStatus == ENTRY_MESSAGE_READ )
		{
		   p = &(fi->FifoBuffer[fi->pRead]); 
		}
		else
		{
			for(;;)
			{
				tmp = fi->FifoBuffer[fi->pRead++];
				
				if ( fi->pRead >= fi->BufferSize )
				{
					fi->pRead = 0;
				}
	
				if ( tmp == 0 ) /* end of entry (string) */
				{
					fi->AvailabelEntryCount--;
					break;
				}
			}
			if ( fi->AvailabelEntryCount > 0 )
			{
				p = &(fi->FifoBuffer[fi->pRead]); 
			}
		}
	}
	
	cpu_restore_sr(save_status_reg);

	return p;
}


/* void Fifo_Entry_Init(FIFO_ENTRY* fe, unsigned char* FifoBuffer, int BufferSize); */
/* void Fifo_Entry_Init(FIFO_ENTRY* fe, unsigned char* FifoBuffer, int BufferSize) */
/* { */
/* 	fe->fifo.pWrite = 0; */
/* 	fe->fifo.pRead = 0; */
/* 	fe->fifo.BufferSize = BufferSize; */
/* 	fe->fifo.FifoBuffer = FifoBuffer; */
/* 	fe->AvailabelEntryCount = 0; */
/* } */



/* return (VCOM_FIFO_SIZE - 1 - fifo_avail(fifo)); */

/* return (VCOM_FIFO_SIZE + fifo->head - fifo->tail) % VCOM_FIFO_SIZE; */

/* int Fifo_AvailableToWrite(FIFO_INF* fi) */
/* { */
/* 	if ( fi->pWrite >= fi->pRead ) */
/* 	{ */
/* 		return( fi->BufferSize - fi->pWrite + fi->pRead - 1); */
/* 	} */
	
/* 	return ( fi->pRead - fi->pWrite - 1); */
/* } */



/* 	if ( Fifo_AvailableToWrite((FIFO_INF*)(&(fe->fifo))) >= ByteCount ) */
/* 	{   */
/* 		for ( i = 0; i < ByteCount; i++ ) */
/* 		{ */
/* 			fe->fifo.FifoBuffer[fe->fifo.pWrite++] = *DataBuffer++; */
		
/* 			if ( fe->fifo.pWrite >= fe->fifo.BufferSize ) */
/* 			{ */
/* 				fe->fifo.pWrite = 0; */
/* 			} */
/* 		}  */
/* 	} */
/* 	else */
/* 	{ */
/* 		i = (-1); */
/* 	} */

/* 	for(;;) */
/* 	{ */
/* 		if ( fe->fifo.pRead == fe->fifo.pWrite ) */
/* 		{ */
/* 			break; */
/* 		} */
		
/* 		DataBuffer[i++] = fe->fifo.FifoBuffer[fe->fifo.pRead++]; */
		
/* 		if ( fe->fifo.pRead >= fe->fifo.BufferSize ) */
/* 		{ */
/* 			fe->fifo.pRead = 0; */
/* 		} */
/* 	} */
